package com.sunyard.manage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.page.PageMethod;
import com.sunyard.dal.bo.device.key.KeyAddBO;
import com.sunyard.dal.bo.device.key.KeyCheckBO;
import com.sunyard.dal.bo.device.key.KeyCheckDetailBO;
import com.sunyard.dal.bo.device.key.KeyCopyQueryBO;
import com.sunyard.dal.bo.device.key.KeyDeleteBO;
import com.sunyard.dal.bo.device.key.KeyQueryBO;
import com.sunyard.dal.bo.device.key.KeyUpdateBO;
import com.sunyard.dal.bo.device.key.KeyUpdateStateBO;
import com.sunyard.dal.bo.device.key.KeyUploadLogBO;
import com.sunyard.dal.bo.PaginationBO;
import com.sunyard.dal.dto.KeyCheckAfterDTO;
import com.sunyard.dal.dto.KeyCheckBeforeDTO;
import com.sunyard.dal.dto.KeyCheckDetailResDTO;
import com.sunyard.dal.dto.KeyCopyQueryResDTO;
import com.sunyard.dal.dto.KeyQueryResDTO;
import com.sunyard.dal.dto.znsTask.TaskZNSDTO;
import com.sunyard.dal.entity.Key;
import com.sunyard.dal.entity.KeyCopy;
import com.sunyard.dal.entity.Lock;
import com.sunyard.dal.entity.OperateHistory;
import com.sunyard.dal.entity.Operator;
import com.sunyard.dal.entity.Organization;
import com.sunyard.dal.mapper.KeyCopyMapper;
import com.sunyard.dal.mapper.KeyMapper;
import com.sunyard.dal.mapper.LockMapper;
import com.sunyard.dal.mapper.OperateHistoryMapper;
import com.sunyard.dal.mapper.OperatorMapper;
import com.sunyard.dal.mapper.OrganizationMapper;
import com.sunyard.dal.mapper.ZNSTaskMapper;
import com.sunyard.enums.IsCheckEnum;
import com.sunyard.enums.IsDeletedEnum;
import com.sunyard.enums.KeyStatusEnum;
import com.sunyard.enums.LockStatusEnum;
import com.sunyard.enums.AuditTypeEnum;
import com.sunyard.manage.service.KeyService;
import com.sunyard.utils.DateUtil;
import com.sunyard.utils.ExcelOutput;
import com.sunyard.utils.Response.BaseResult;
import com.sunyard.utils.Response.GetResult;
import com.sunyard.utils.TokenUtil;
import com.sunyard.utils.manage.DataGrid;
import com.sunyard.utils.manage.PageQuery;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static java.util.stream.Collectors.toList;

@Service
@Slf4j
public class KeyServiceImpl implements KeyService {

    @Autowired
    KeyMapper keyMapper;

    @Autowired
    KeyCopyMapper keyCopyMapper;

    @Autowired
    OrganizationMapper organizationMapper;

    @Autowired
    OperatorMapper operatorMapper;

    @Autowired
    OperateHistoryMapper operateHistoryMapper;

    @Autowired
    ZNSTaskMapper znsTaskMapper;

    @Autowired
    LockMapper lockMapper;

    /**
     * 分页查询终端信息
     *
     * @param queryBO [queryBO]
     * @return BaseResult<DataGrid < KeyQueryResDTO>>
     **/
    @Override
    public BaseResult<DataGrid<KeyQueryResDTO>> getKeyByPage(PaginationBO<KeyQueryBO> queryBO, HttpServletRequest request) {
        KeyQueryBO keyQueryBO = queryBO.getParams();
        log.info("终端信息查询入参：{}", JSON.toJSONString(keyQueryBO));
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        if (StringUtils.isBlank(keyQueryBO.getOrgId())) {
            keyQueryBO.setOrgId(orgId);
        }
        //设置分页信息
        PageMethod.startPage(queryBO.getPageNo(), queryBO.getPageSize());
        List<Key> keyList = keyMapper.getKeyByPage(keyQueryBO);
        List<KeyQueryResDTO> resList = new ArrayList<>();
        for (Key key : keyList) {
            KeyQueryResDTO resDTO = new KeyQueryResDTO();
            BeanUtil.copyProperties(key, resDTO);
            resDTO.setCreateTime(DateUtil.getDateStr(DateUtil.YYYYMMDD_HHMMSS, key.getCreateTime()));
            Organization organization = organizationMapper.getOrganizationByOrgId(String.valueOf(key.getOrgId()));
            resDTO.setOrgName(organization.getOrgName());
            Operator operator = operatorMapper.getOperatorByOpId(key.getCreateUser());
            resDTO.setCreateUser(operator.getOpName());
            resList.add(resDTO);
        }
        DataGrid dataGrid = PageQuery.getDataGrids(keyList, resList);
        return GetResult.getResult(dataGrid);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult addKey(KeyAddBO addBO, HttpServletRequest request) {
        String opId = TokenUtil.getOpId(request.getHeader("token"));
        //判断终端名称是否已经存在
        Key key = keyMapper.getKeyByKeyName(addBO.getKeyName());
        if (!ObjectUtil.isNull(key)) {
            return GetResult.getResultFail("终端名已存在");
        }
        //判断终端Mac地址是否存在
        Key keyMac = keyMapper.getKeyByMac(addBO.getMac());
        if (ObjectUtil.isNotNull(keyMac)) {
            return GetResult.getResultFail("mac地址已存在");
        }
        Key addKey = new Key();
        BeanUtil.copyProperties(addBO, addKey);
        //添加终端时设置终端状态为启用状态
        addKey.setStatus(KeyStatusEnum.ENABLE.getCode());
        addKey.setCreateUser(opId);
        addKey.setCreateTime(new Date());
        addKey.setIsDeleted(IsDeletedEnum.NOT_DELETED.getCode());
        addKey.setIsCheck(addBO.getIsCheck());
        //添加数据到终端表中
        int insert = keyMapper.insert(addKey);
        if (insert <= 0) {
            return GetResult.getResultFail("添加终端信息失败");
        }
        //获取到刚添加到的终端信息
        Key selectKey = keyMapper.getKeyByKeyName(addBO.getKeyName());
        KeyCopy keyCopy = new KeyCopy();
        BeanUtil.copyProperties(addKey, keyCopy);
        keyCopy.setAdminId(addBO.getAdminId());
        keyCopy.setOperateType(AuditTypeEnum.ADD.getCode());
        keyCopy.setKeyId(selectKey.getId());
        if (!"0".equals(addBO.getIsCheck())) {
            //如果是同步审核，则复核人为申请复核人
            keyCopy.setCheckAdminId(addBO.getAdminId());
        }
        //添加审核信息
        int insert1 = keyCopyMapper.insert(keyCopy);
        /*if (true){
            throw new RuntimeException();
        }*/
        if (insert1 <= 0) {
            return GetResult.getResultFail("添加终端审核信息失败");
        }
        return GetResult.getResultSuccess("添加终端成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult deleteKey(KeyDeleteBO deleteBO) {
        Key key = keyMapper.selectByPrimaryKey(Integer.valueOf(deleteBO.getId()));
        if (ObjectUtil.isNull(key)) {
            return GetResult.getResultFail("未查询到该终端信息，请核对");
        }
        //添加审核信息
        addKeyCopy(key, deleteBO.getIsCheck(), deleteBO.getAdminId(), AuditTypeEnum.DELETE.getCode());
        key.setIsDeleted(IsDeletedEnum.DELETED.getCode());
        key.setIsCheck(deleteBO.getIsCheck());
        //如果为已审核，则修改信息表中的删除状态为已删除
        if (!"0".equals(deleteBO.getIsCheck())) {
            int update = keyMapper.updateByPrimaryKey(key);
            if (update <= 0) {
                return GetResult.getResultFail("删除终端信息失败");
            }
        }
        return GetResult.getResultSuccess("操作成功");
    }

    /**
     * 添加审核信息
     *
     * @param key         终端信息
     * @param isCheck     审核状态 0待复核 1已复核
     * @param adminId     申请复核人，不限制时填0
     * @param operateType 复核类型 1添加 2修改 3删除
     **/

    private void addKeyCopy(Key key, String isCheck, String adminId, String operateType) {
        //查询该终端是否存在添加审核
        KeyCopy keyCopy = keyCopyMapper.selectByKeyId(key.getId());
        if (ObjectUtil.isNull(keyCopy)) {
            keyCopy = new KeyCopy();
        }
        keyCopy.setKeyName(key.getKeyName());
        keyCopy.setKeyType(key.getKeyType());
        keyCopy.setMac(key.getMac());
        keyCopy.setOrgId(key.getOrgId());
        keyCopy.setOverUse(key.getOverUse());
        keyCopy.setRemark(key.getRemark());
        keyCopy.setCreateTime(key.getCreateTime());
        keyCopy.setCreateUser(key.getCreateUser());
        keyCopy.setStatus(key.getStatus());
        keyCopy.setKeyId(key.getId());
        if (AuditTypeEnum.ADD.getCode().equals(keyCopy.getOperateType()) && keyCopy.getId() != null) {
            throw new IllegalArgumentException("该终端添加审核中，无法删除");
        }
        keyCopy.setOperateType(operateType);
        keyCopy.setIsCheck(isCheck);
        keyCopy.setAdminId(adminId);
        if (!"0".equals(isCheck)) {
            //如果是同步审核，则复核人为申请复核人
            keyCopy.setCheckAdminId(adminId);
        }
        if (keyCopy.getId() != null) {
            keyCopyMapper.updateByPrimaryKey(keyCopy);
        } else {
            keyCopyMapper.insert(keyCopy);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult updateKey(KeyUpdateBO updateBO) {
        Key key = keyMapper.selectByPrimaryKey(Integer.valueOf(updateBO.getId()));
        if (ObjectUtil.isNull(key)) {
            return GetResult.getResultFail("未查询到该终端信息，请核对");
        }
        //判断钥匙名称是否已经存在
        Key checkName = keyMapper.selectByNameAndId(updateBO.getKeyName(), updateBO.getId());
        if (ObjectUtil.isNotNull(checkName)) {
            return GetResult.getResultFail("终端名称已存在");
        }
        //判断Mac地址是否已经存在
        Key checkMac = keyMapper.selectByMacAndId(updateBO.getMac(), updateBO.getId());
        if (ObjectUtil.isNotNull(checkMac)) {
            return GetResult.getResultFail("mac地址已存在");
        }
        key.setKeyName(updateBO.getKeyName());
        key.setKeyType(updateBO.getKeyType());
        key.setMac(updateBO.getMac());
        key.setOrgId(Integer.valueOf(updateBO.getOrgId()));
        key.setRemark(updateBO.getRemark());
        key.setIsCheck(updateBO.getIsCheck());
        //添加审核信息
        addKeyCopy(key, updateBO.getIsCheck(), updateBO.getAdminId(), AuditTypeEnum.UPDATE.getCode());
        //判断入伙为同步审核，则直接修改信息表中的信息
        if (!"0".equals(updateBO.getIsCheck())) {
            keyMapper.updateByPrimaryKey(key);
        } else {
            Key updateCheck = new Key();
            updateCheck.setId(Integer.valueOf(updateBO.getId()));
            updateCheck.setIsCheck(updateBO.getIsCheck());
            keyMapper.updateByPrimaryKeySelective(updateCheck);
        }
        return GetResult.getResultSuccess("操作成功");
    }

    @Override
    public BaseResult updateState(KeyUpdateStateBO updateStateBO) {
        Key key = keyMapper.selectByPrimaryKey(Integer.valueOf(updateStateBO.getId()));
        if (ObjectUtil.isNull(key)) {
            return GetResult.getResultFail("未查询到该终端信息，请核对");
        }
        key.setStatus(updateStateBO.getStatus());
        key.setIsCheck(updateStateBO.getIsCheck());
        addKeyCopy(key, updateStateBO.getIsCheck(), updateStateBO.getAdminId(), AuditTypeEnum.UPDATE.getCode());
        String message = "1".equals(updateStateBO.getStatus()) ? "启用" : "停用";
        if (!"0".equals(updateStateBO.getIsCheck())) {
            keyMapper.updateByPrimaryKey(key);
            return GetResult.getResultSuccess(message + "成功");
        }
        return GetResult.getResultSuccess(message + "成功,待审核");
    }

    @Override
    public BaseResult exportKey(HttpServletRequest request, HttpServletResponse response) throws Exception {
        List<Key> keyList = keyMapper.getKeyList();
        String title = "终端信息导出";
        String[] headers = new String[]{"终端名称", "终端类型", "Mac地址", "所属机构ID", "所属机构名称", "是否超出电子围栏使用", "终端状态", "备注", "创建时间", "创建人ID", "创建人名称"};
        List<Object[]> dataList = new ArrayList<Object[]>();
        String[] keyType = {"指纹终端", "物联网终端", "动码终端"};
        String[] overUse = {"否", "是"};
        String[] status = {"启用", "停用"};
        dataList = keyList.stream().map(key -> {
            Object[] obj = new Object[headers.length];
            obj[0] = key.getKeyName();
            obj[1] = keyType[Integer.parseInt(key.getKeyType()) - 1];
            obj[2] = key.getMac();
            obj[3] = key.getOrgId();
            Organization organization = organizationMapper.getOrganizationByOrgId(String.valueOf(key.getOrgId()));
            obj[4] = organization.getOrgName();
            obj[5] = overUse[Integer.parseInt(key.getOverUse()) - 1];
            obj[6] = status[Integer.parseInt(key.getStatus()) - 1];
            obj[7] = key.getRemark();
            obj[8] = DateUtil.getDateStr(DateUtil.YYYYMMDD_HHMMSS, key.getCreateTime());
            obj[9] = key.getCreateUser();
            Operator operator = operatorMapper.getOperatorByOpId(key.getCreateUser());
            obj[10] = operator.getOpName();
            return obj;
        }).collect(toList());
        OutputStream out = null;
        // 防止中文乱码
        String headStr = "attachment; filename=\"" + new String(title.getBytes("gb2312"), "ISO8859-1") + "\"";
        response.setContentType("octets/stream");
        response.setContentType("APPLICATION/OCTET-STREAM");
        response.setHeader("Content-Disposition", headStr);
        out = response.getOutputStream();
        ExcelOutput ex = new ExcelOutput(title, headers, dataList);
        ex.export(out);
        return null;
    }

    @Override
    public BaseResult uploadLog(KeyUploadLogBO uploadLogBO, HttpServletRequest request) {
        //通过任务编号查询是否存在改任务信息
        TaskZNSDTO taskZNSDTO = znsTaskMapper.selectById(uploadLogBO.getMissionId());
        if (ObjectUtil.isNull(taskZNSDTO)) {
            return GetResult.getResultFail("任务不存在");
        }
        //通过钥匙Mac地址查询钥匙信息
        Key key = keyMapper.getKeyByMac(uploadLogBO.getMac());
        if (ObjectUtil.isNull(key)) {
            return GetResult.getResultFail("终端不存在");
        }
        if ("".equals(uploadLogBO.getUser1())) {
            return GetResult.getResultFail("user1为空");
        }
        OperateHistory operateHistory = new OperateHistory();
        operateHistory.setLockStatus(uploadLogBO.getLockStatus());
        if ("成功".equals(uploadLogBO.getOperateStatus())) {
            operateHistory.setOperateStatus("1");
        } else {
            operateHistory.setOperateStatus("2");
        }
        operateHistory.setOperateTime(uploadLogBO.getOperateTime());
        String lockId = uploadLogBO.getLockId().replace("\u0000", "");
        int index = 0;
        for (int i = 0; i < lockId.length(); i++) {
            if ('0' != lockId.charAt(i)) {
                index = i;
                break;
            }
        }
        Lock lock = lockMapper.selectByPrimaryKey(Integer.parseInt(lockId.substring(index)));
        operateHistory.setOperateType(uploadLogBO.getOperateType());
        if ("2".equals(lock.getReversion())) {
            if ("01-开锁".equals(uploadLogBO.getOperateType())) {
                operateHistory.setOperateType("02-关锁");
                lock.setLockStatus(LockStatusEnum.DISABLE.getCode());
            }
            if ("02-关锁".equals(uploadLogBO.getOperateType())) {
                operateHistory.setOperateType("01-开锁");
                lock.setLastTime(String.valueOf(System.currentTimeMillis()));
                lock.setLockStatus(LockStatusEnum.ENABLE.getCode());
            }
        } else {
            if ("01-开锁".equals(uploadLogBO.getOperateType())) {
                lock.setLockStatus(LockStatusEnum.ENABLE.getCode());
                lock.setLastTime(String.valueOf(System.currentTimeMillis()));
            }
            if ("02-关锁".equals(uploadLogBO.getOperateType())) {
                lock.setLockStatus(LockStatusEnum.DISABLE.getCode());
            }
        }
        operateHistory.setLockId(lockId);

        operateHistory.setMissionId(uploadLogBO.getMissionId());
        operateHistory.setCollectTime(new Date());
        operateHistory.setUser1(uploadLogBO.getUser1());
        if (!"".equals(uploadLogBO.getUser2())) {
            operateHistory.setUser2(uploadLogBO.getUser2());
        } else {
            operateHistory.setUser2("0");
        }
        operateHistory.setKeyId(key.getId());
        operateHistory.setMac(uploadLogBO.getMac());
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        operateHistory.setOrgId(orgId);
        operateHistory.setMissionType(taskZNSDTO.getTaskTypeName());
        operateHistory.setStatus("1");
        operateHistoryMapper.insert(operateHistory);
        lockMapper.updateByPrimaryKeySelective(lock);
        key.setLastTime(String.valueOf(System.currentTimeMillis()));
        keyMapper.updateByPrimaryKeySelective(key);
        return GetResult.getResultSuccess("导入成功");
    }

    @Override
    public BaseResult checkKey(KeyCheckBO checkBO, HttpServletRequest request) {
        KeyCopy keyCopy = keyCopyMapper.selectByPrimaryKey(Integer.valueOf(checkBO.getId()));
        if (ObjectUtil.isNull(keyCopy)) {
            return GetResult.getResultFail("未查询到审核信息");
        }
        //通过终端ID查询终端信息
        Key key = keyMapper.selectByPrimaryKey(keyCopy.getKeyId());
        if (ObjectUtil.isNull(key)) {
            return GetResult.getResultFail("终端不存在");
        }
        String opId = TokenUtil.getOpId(request.getHeader("token"));
        if (!opId.equals(String.valueOf(keyCopy.getAdminId()))) {
            return GetResult.getResultFail("您没有审核该信息的权限");
        }
        //如果为审核不通过，则只需要修改审核状态和审核详情,如果为审核通过，则修改信息表信息
        if (IsCheckEnum.PASS_CHECKED.getCode().equals(checkBO.getIsCheck())) {
            //如果为添加审核，则直接修改山河状态为已审核
            if (AuditTypeEnum.UPDATE.getCode().equals(keyCopy.getOperateType())) {
                //如果为修改审核，则修改信息表中的对应信息
                key.setKeyName(keyCopy.getKeyName());
                key.setKeyType(keyCopy.getKeyType());
                key.setMac(keyCopy.getMac());
                key.setOrgId(keyCopy.getOrgId());
                key.setRemark(keyCopy.getRemark());
                key.setStatus(keyCopy.getStatus());
            } else {
                //如果为删除审核，则修改信息表删除标志位已删除，审核表状态改为已审核
                key.setIsDeleted(IsDeletedEnum.DELETED.getCode());
            }
        }
        keyCopy.setCheckAdminId(opId);
        keyCopy.setIsCheck(checkBO.getIsCheck());
        keyCopy.setAuditDesc(checkBO.getAuditDesc());
        keyCopyMapper.updateByPrimaryKey(keyCopy);
        key.setIsCheck(checkBO.getIsCheck());
        keyMapper.updateByPrimaryKey(key);
        return GetResult.getResultSuccess("操作成功");
    }

    @Override
    public BaseResult<DataGrid<KeyCopyQueryResDTO>> getKeyCopyByPage(PaginationBO<KeyCopyQueryBO> queryBO, HttpServletRequest request) {
        KeyCopyQueryBO keyCopyQueryBO = queryBO.getParams();
        log.info("终端信息查询入参：{}", JSON.toJSONString(keyCopyQueryBO));
        String opId = TokenUtil.getOpId(request.getHeader("token"));
        keyCopyQueryBO.setAdminId(opId);
        //设置分页信息
        PageMethod.startPage(queryBO.getPageNo(), queryBO.getPageSize());
        List<KeyCopy> keyCopyList = keyCopyMapper.getKeyCopyByPage(keyCopyQueryBO);
        List<KeyCopyQueryResDTO> resList = new ArrayList<>();
        for (KeyCopy keyCopy : keyCopyList) {
            KeyCopyQueryResDTO resDTO = new KeyCopyQueryResDTO();
            BeanUtil.copyProperties(keyCopy, resDTO);
            resDTO.setCreateTime(DateUtil.getDateStr(DateUtil.YYYYMMDD_HHMMSS, keyCopy.getCreateTime()));
            Organization organization = organizationMapper.getOrganizationByOrgId(String.valueOf(keyCopy.getOrgId()));
            resDTO.setOrgName(organization.getOrgName());
            Operator operator = operatorMapper.getOperatorByOpId(keyCopy.getCreateUser());
            resDTO.setCreateUser(operator.getOpName());
            operator = operatorMapper.getOperatorByOpId(keyCopy.getAdminId());
            if (ObjectUtil.isNotNull(operator)) {
                resDTO.setAdminId(operator.getOpName());
            }
            operator = operatorMapper.getOperatorByOpId(keyCopy.getCheckAdminId());
            if (ObjectUtil.isNotNull(operator)) {
                resDTO.setCheckAdminId(operator.getOpName());
            }
            resList.add(resDTO);
        }
        DataGrid dataGrid = PageQuery.getDataGrids(keyCopyList, resList);
        return GetResult.getResult(dataGrid);
    }

    @Override
    public BaseResult<KeyCheckDetailResDTO> checkDetail(KeyCheckDetailBO checkBO, HttpServletRequest request) {
        KeyCheckDetailResDTO detailResDTO = new KeyCheckDetailResDTO();
        KeyCopy keyCopy = keyCopyMapper.selectByPrimaryKey(Integer.valueOf(checkBO.getId()));
        KeyCheckAfterDTO afterDTO = new KeyCheckAfterDTO();
        BeanUtil.copyProperties(keyCopy, afterDTO);
        Key key = keyMapper.selectByPrimaryKey(keyCopy.getKeyId());
        KeyCheckBeforeDTO beforeDTO = new KeyCheckBeforeDTO();
        BeanUtil.copyProperties(key, beforeDTO);
        //如果为增加审核，则审核前数据为空
        if (AuditTypeEnum.ADD.getCode().equals(keyCopy.getOperateType())) {
            detailResDTO.setBeforeDTO(null);
        } else if (AuditTypeEnum.DELETE.getCode().equals(keyCopy.getOperateType())) {
            //如果是删除审核，则设置审核信息的删除标识为已删除
            afterDTO.setIsDeleted(IsDeletedEnum.DELETED.getCode());
            detailResDTO.setAfterDTO(afterDTO);
        } else {
            afterDTO.setIsDeleted(IsDeletedEnum.NOT_DELETED.getCode());
            detailResDTO.setAfterDTO(afterDTO);
        }
        detailResDTO.setBeforeDTO(beforeDTO);
        return GetResult.getResult(detailResDTO);
    }
}
